"""
api服务接口
"""
from fastapi import Body
from services.api_wrap import async_api_wrapper
from fastapi import UploadFile, File
from starlette.responses import FileResponse
from typing import Optional
from pydantic import Field
from pathlib import Path
import docker
import subprocess
import tempfile
import os


uploadFiles = Path(__file__).parent.parent / "files"
_docker = docker.from_env()


def get_container(
        name: str = Field(default="python-sandbox", description="容器名称."),
        container_id: Optional[str] = Field(default=None, description="容器id."),
):
    """根据容器名称/容器id找到容器"""
    if container_id is not None:
        container = _docker.containers.get(container_id)
        return container
    else:
        containers = _docker.containers.list(all=True, filters={
            'name': name
        })
        for container in containers:
            if container.name == name:
                return container
        return None


@async_api_wrapper
async def upload_file_api(
        user_id: str = Body('123', description='用户id'),
        file: UploadFile = File(...),
        docker_name: str = Body("hardcore_hamilton", description='mcp容器名')
):
    # 接收用户的上传文件，先保存在当前服务器目录。
    contents = await file.read()
    local_file = uploadFiles / file.filename
    with open(local_file, 'wb') as fw:
        fw.write(contents)

    # 获取docker
    container = get_container(docker_name, None)
    if container is None:
        return {'success': False, 'message': '未找到相应的容器.'}

    # 创建用户目录， 若没有则不创建
    user_dir = Path('/files') / user_id
    command = f"docker exec -i {container.short_id} mkdir -p {user_dir}"
    subprocess.run(command, shell=True, capture_output=True)

    # 再传到docker_name对应的容器中。
    container_file = Path('/files') / user_id / file.filename
    command = f"docker cp '{local_file}' {container.short_id}:'{container_file}'"
    result = subprocess.run(command, shell=True, capture_output=True)
    if result.returncode == 0:
        return {'success': True, 'message': result.stdout}
    else:
        return {'success': False, 'message': result.stderr.decode()}


@async_api_wrapper
async def list_files_api(
        user_id: str = Body('123', description='用户id'),
        docker_name: str = Body("hardcore_hamilton", description='mcp容器名')
):
    # 获取docker
    container = get_container(docker_name, None)
    if container is None:
        return {'success': False, 'message': '未找到相应的容器.'}

    # 列目录
    user_dir = Path('/files') / user_id
    command = f"docker exec -i {container.short_id} ls -al {user_dir}"
    result = subprocess.run(command, shell=True, capture_output=True)
    if result.returncode == 0:
        return {'success': True, 'message': result.stdout}
    else:
        return {'success': False, 'message': result.stderr.decode()}


@async_api_wrapper
async def download_files_api(
        user_id: str = Body('123', description='用户id'),
        filename: str = Body(..., description='文件名'),
        docker_name: str = Body("hardcore_hamilton", description='mcp容器名')
):
    container = get_container(docker_name, None)
    if container is None:
        return {'success': False, 'message': '未找到相应的容器.'}

    # 将容器内的用户文件拷贝到服务器文件目录
    container_file = Path('/files') / user_id / filename
    local_file = uploadFiles / filename
    command = f"docker cp {container.short_id}:'{container_file}' '{local_file}'"
    result = subprocess.run(command, shell=True, capture_output=True)
    if result.returncode != 0:
        return {'success': False, 'message': result.stderr.decode()}

    # 再发送文件
    return FileResponse(local_file, filename=filename)


@async_api_wrapper
async def create_mcp_proxy_api(
        config: str = Body(..., description='mcp配置', example="""
"mcpServers": {
    "sequential-thinking": {
      "command": "npx",
      "args": [
        "-y",
        "@modelcontextprotocol/server-sequential-thinking"
      ]
    },
    "files": {
      "command": "npx",
      "args": [
        "-y",
        "@modelcontextprotocol/server-filesystem",
        "/files"
      ]
    }
}"""),
        port: str = Body(..., description='端口号'),
        docker_name: str = Body(..., description='mcp容器名')
):
    """基于mcp_proxy创建沙箱mcp-sse服务"""
    mcp_proxy_config = """
{
  "mcpProxy": {
    "baseURL": "0.0.0.0",
    "addr": ":9090",
    "name": "MCP Proxy",
    "version": "1.0.0",
    "options": {
      "panicIfInvalid": false,
      "logEnabled": false
    }
  },
  %s
}""" % config

    fw = tempfile.NamedTemporaryFile(delete=False, suffix=".json", mode='w', encoding="utf-8")
    fw.write(mcp_proxy_config)
    fw.close()

    # 从镜像创建并运行容器
    args = {
        'image': 'ghcr.io/tbxark/mcp-proxy',
        'name': f'{docker_name}',
        'network': 'bridge',
        'ports': {'9090/tcp': port},
        'volumes': {f"{fw.name}:/config/config.json"}
    }
    container = _docker.containers.create(**args)
    container.start()
    container_info = {
        "id": container.id,
        "name": container.name,
        "short_id": container.short_id,
        "status": container.status
    }
    os.unlink(fw.name)
    return container_info
